package com.yike.user.mq;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yike.common.constant.RocketMqConstant;
import com.yike.common.entity.CommissionGoodsMq;
import com.yike.common.entity.CommissionOrderMq;
import com.yike.common.exception.BusinessException;
import com.yike.common.tool.DateUtil;
import com.yike.user.entity.*;
import com.yike.user.mapper.*;
import com.yike.user.vo.AgentCountDataVo;
import lombok.extern.java.Log;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Log
@Component
@RocketMQMessageListener(topic = RocketMqConstant.AGENT_COMMISSION_TOPIC, consumerGroup = RocketMqConstant.AGENT_COMMISSION_GROUP, consumeThreadMax = 10)
public class AgentCommissionListener implements RocketMQListener<CommissionOrderMq> {

    @Autowired
    private AgentShopCountMapper agentShopCountMapper;
    @Autowired
    private ShopMapper shopMapper;
    @Autowired
    private AgentMapper agentMapper;
    @Autowired
    private AgentShopMapper agentShopMapper;
    @Autowired
    private GoodsCountMapper goodsCountMapper;
    @Autowired
    private ShopCountMapper shopCountMapper;
    @Autowired
    private AgentCountMapper agentCountMapper;
    @Autowired
    private CategoryCountMapper categoryCountMapper;
    @Autowired
    private RedissonClient redissonClient;

    // 这里主要是用来处理当天订单汇总统计，数据不一定准确
    @Override
    public void onMessage(CommissionOrderMq commissionOrderMq) {
        log.info(RocketMqConstant.AGENT_COMMISSION_TOPIC + " 接收到消息：" + JSON.toJSONString(commissionOrderMq));
        // 获取店铺信息和对应的商家信息，得到平台分润
        Shop shop = shopMapper.selectById(commissionOrderMq.getShopId());
        if (shop == null) {
            log.info(commissionOrderMq.getShopId() + " 店铺信息异常");
        }

        // 通过Redisson配置分布式全局锁保证数据安全性
        RLock stockLock = redissonClient.getLock("agent_commission_listener_" + shop.getId());
        try {
            //尝试加锁, 最多等待3秒, 10秒后自动解锁
            boolean getStockLock = stockLock.tryLock(3, 5, TimeUnit.SECONDS);
            if (getStockLock) {
                if (shop.getCommissionRate() != null) {
                    // 顺便在此处处理一下订单分佣，此处计算意义不大，金额太小基本没有了，但建议保留
                    agentShopCountMapper.updateOrderCommission(commissionOrderMq.getOrderId(), shop.getCommissionRate());
                    ShopCount shopCount = shopCountMapper.selectOne(Wrappers.lambdaQuery(ShopCount.class)
                            .eq(ShopCount::getShopId, shop.getId())
                            .eq(ShopCount::getCountDate, DateUtil.format(commissionOrderMq.getPayTime(), "yyyy-MM-dd")));
                    if (shopCount == null) {
                        shopCount = new ShopCount();
                        shopCount.setShopId(commissionOrderMq.getShopId());
                        shopCount.setCountDate(commissionOrderMq.getPayTime());
                        shopCount.setCommissionAmount(new BigDecimal("0"));
                        shopCount.setTotalAmount(new BigDecimal("0"));
                        shopCount.setActualAmount(new BigDecimal("0"));
                        shopCount.setWxAmount(new BigDecimal("0"));
                        shopCount.setAliAmount(new BigDecimal("0"));
                        shopCount.setOrderNumber(0);
                        shopCount.setRefundNumber(0);
                        shopCount.setWxOrderNumber(0);
                        shopCount.setAliOrderNumber(0);

                        shopCountMapper.insert(shopCount);
                    }

                    // 1：支付 2：退款
                    if (commissionOrderMq.getType() == 1) {
                        shopCount.setOrderNumber(shopCount.getOrderNumber() + 1);
                        shopCount.setTotalAmount(shopCount.getTotalAmount().add(commissionOrderMq.getAmount()));
                        shopCount.setActualAmount(shopCount.getActualAmount().add(commissionOrderMq.getAmount()));

                        // 1微信 2支付宝
                        if (commissionOrderMq.getPayway() == 1) {
                            shopCount.setWxOrderNumber(shopCount.getWxOrderNumber() + 1);
                            shopCount.setWxAmount(shopCount.getWxAmount().add(commissionOrderMq.getAmount()));
                        }
                        if (commissionOrderMq.getPayway() == 2) {
                            shopCount.setAliOrderNumber(shopCount.getAliOrderNumber() + 1);
                            shopCount.setAliAmount(shopCount.getAliAmount().add(commissionOrderMq.getAmount()));
                        }
                    }
                    if (commissionOrderMq.getType() == 2) {
                        shopCount.setRefundNumber(shopCount.getRefundNumber() + 1);
                        shopCount.setActualAmount(shopCount.getActualAmount().subtract(commissionOrderMq.getAmount()));

                        // 1微信 2支付宝
                        if (commissionOrderMq.getPayway() == 1) {
                            shopCount.setWxAmount(shopCount.getWxAmount().subtract(commissionOrderMq.getAmount()));
                        }
                        if (commissionOrderMq.getPayway() == 2) {
                            shopCount.setAliAmount(shopCount.getAliAmount().subtract(commissionOrderMq.getAmount()));
                        }
                    }
                    shopCount.setCommissionRate(shop.getCommissionRate());
                    BigDecimal shopCommission = shopCount.getActualAmount().multiply(shop.getCommissionRate()).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
                    shopCount.setCommissionAmount(shopCommission);

                    shopCountMapper.updateById(shopCount);

                    // 获取店铺代理商信息计算代理商费率
                    AgentShop agentShop = agentShopMapper.selectOne(Wrappers.lambdaQuery(AgentShop.class)
                            .eq(AgentShop::getShopId, commissionOrderMq.getShopId()));
                    if (agentShop != null) {
                        // 获取代理商信息
                        Agent agent = agentMapper.selectById(agentShop.getAgentId());
                        if (agent != null && agent.getCommissionRate() != null) {
                            // 计算当前代理商分润，分润是百分比需要转换
                            BigDecimal agentCommission = shopCount.getActualAmount().multiply(agent.getCommissionRate()).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);

                            AgentShopCount agentShopCount = agentShopCountMapper.selectOne(Wrappers.lambdaQuery(AgentShopCount.class)
                                    .eq(AgentShopCount::getAgentId, agent.getId())
                                    .eq(AgentShopCount::getShopCountId, shopCount.getId()));
                            if (agentShopCount == null) {
                                agentShopCount = new AgentShopCount();
                                agentShopCount.setShopCountId(shopCount.getId());
                                agentShopCount.setAgentId(agent.getId());
                                agentShopCountMapper.insert(agentShopCount);
                            }

                            agentShopCount.setParentFlag(false);
                            agentShopCount.setCommissionAmount(agentCommission);
                            agentShopCount.setCommissionRate(agent.getCommissionRate());
                            agentShopCountMapper.updateById(agentShopCount);

                            // 汇总代理商分润，因为一个代理商可能有很多店铺
                            AgentCount agentCount = agentCountMapper.selectOne(Wrappers.lambdaQuery(AgentCount.class)
                                    .eq(AgentCount::getAgentId, agent.getId())
                                    .eq(AgentCount::getCountDate, shopCount.getCountDate()));
                            if (agentCount == null) {
                                agentCount = new AgentCount();
                                agentCount.setAgentId(agent.getId());
                                agentCount.setCountDate(commissionOrderMq.getPayTime());
                                agentCount.setCommissionAmount(new BigDecimal("0"));
                                agentCount.setTotalAmount(new BigDecimal("0"));
                                agentCount.setActualAmount(new BigDecimal("0"));
                                agentCountMapper.insert(agentCount);
                            }
                            AgentCountDataVo agentCountDataVo = agentShopCountMapper.getAgentCountDataVo(agent.getId(), DateUtil.format(commissionOrderMq.getPayTime(), "yyyy-MM-dd"));
                            agentCount.setCommissionAmount(agentCountDataVo.getCommissionAmount());
                            agentCount.setTotalAmount(agentCountDataVo.getTotalAmount());
                            agentCount.setActualAmount(agentCountDataVo.getActualAmount());
                            agentCountMapper.updateById(agentCount);
                            // 如果parentId不为0则说明还有上级代理商，上级代理商也需要分润
                            if (agent.getParentId() != 0) {
                                // 获取上级代理商信息
                                Agent parentAgent = agentMapper.selectById(agent.getParentId());
                                if (parentAgent != null && parentAgent.getCommissionRate() != null) {
                                    // 这里要注意上级代理的分润是需要扣除下级的分润的，所以上级的比例必须大于下级才可以进行分润
                                    if (parentAgent.getCommissionRate().compareTo(agent.getCommissionRate()) > 0) {
                                        // 计算上级代理商分润
                                        BigDecimal parentRate = parentAgent.getCommissionRate().subtract(agent.getCommissionRate());
                                        BigDecimal parentCommission = shopCount.getActualAmount().multiply(parentRate).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);

                                        AgentShopCount parentAgentShopCount = agentShopCountMapper.selectOne(Wrappers.lambdaQuery(AgentShopCount.class)
                                                .eq(AgentShopCount::getAgentId, parentAgent.getId())
                                                .eq(AgentShopCount::getShopCountId, shopCount.getId()));
                                        if (parentAgentShopCount == null) {
                                            parentAgentShopCount = new AgentShopCount();
                                            parentAgentShopCount.setShopCountId(shopCount.getId());
                                            parentAgentShopCount.setAgentId(parentAgent.getId());
                                            agentShopCountMapper.insert(parentAgentShopCount);
                                        }

                                        parentAgentShopCount.setParentFlag(true);
                                        parentAgentShopCount.setCommissionAmount(parentCommission);
                                        parentAgentShopCount.setCommissionRate(parentRate);
                                        agentShopCountMapper.updateById(parentAgentShopCount);

                                        // 汇总代理商分润，因为一个代理商可能有很多店铺
                                        AgentCount parentAgentCount = agentCountMapper.selectOne(Wrappers.lambdaQuery(AgentCount.class)
                                                .eq(AgentCount::getAgentId, parentAgent.getId())
                                                .eq(AgentCount::getCountDate, shopCount.getCountDate()));
                                        if (parentAgentCount == null) {
                                            parentAgentCount = new AgentCount();
                                            parentAgentCount.setAgentId(parentAgent.getId());
                                            parentAgentCount.setCountDate(commissionOrderMq.getPayTime());
                                            parentAgentCount.setCommissionAmount(new BigDecimal("0"));
                                            parentAgentCount.setTotalAmount(new BigDecimal("0"));
                                            parentAgentCount.setActualAmount(new BigDecimal("0"));
                                            agentCountMapper.insert(parentAgentCount);
                                        }
                                        AgentCountDataVo parentAgentCountDataVo = agentShopCountMapper.getAgentCountDataVo(parentAgent.getId(), DateUtil.format(commissionOrderMq.getPayTime(), "yyyy-MM-dd"));
                                        parentAgentCount.setCommissionAmount(parentAgentCountDataVo.getCommissionAmount());
                                        parentAgentCount.setTotalAmount(parentAgentCountDataVo.getTotalAmount());
                                        parentAgentCount.setActualAmount(parentAgentCountDataVo.getActualAmount());
                                        agentCountMapper.updateById(parentAgentCount);
                                    } else {
                                        log.info(parentAgent.getId() + " 父代理商分润信息异常");
                                    }
                                } else {
                                    log.info(agent.getId() + " 父代理商信息异常");
                                }
                            }
                        } else {
                            log.info(shop.getId() + " 代理商信息异常");
                        }
                    } else {
                        log.info(commissionOrderMq.getOrderId() + " 店铺信息异常");
                    }
                }
            }

            // 顺便除了商品数据的统计
            GoodsCount(commissionOrderMq.getGoodsMqs(), commissionOrderMq.getType());
        } catch (Exception e) {
            e.printStackTrace();
            log.info("订单分润接口出现异常+++++++++++++++++++++++++++++");
            //throw new BusinessException(500, e.getMessage());
        } finally {
            //解锁
            if (stockLock.isLocked() && stockLock.isHeldByCurrentThread()) {
                stockLock.unlock();
            }
        }

    }

    // 处理商品汇总统计
    public void GoodsCount(List<CommissionGoodsMq> goodsMqs, Integer type) {
        for (CommissionGoodsMq commissionGoodsMq : goodsMqs) {
            // 先获取商品统计数据
            GoodsCount goodsCount = goodsCountMapper.selectOne(Wrappers.lambdaQuery(GoodsCount.class)
                    .eq(GoodsCount::getGoodsId, commissionGoodsMq.getGoodsId()));
            if (goodsCount == null) {
                goodsCount = new GoodsCount();
                goodsCount.setGoodsId(commissionGoodsMq.getGoodsId());
                goodsCount.setTotalAmount(new BigDecimal("0"));
                goodsCount.setBuyNumber(0);
                goodsCount.setRefundNumber(0);
                goodsCount.setOrderNumber(0);
                goodsCount.setRepeatOrderNumber(0);
                goodsCountMapper.insert(goodsCount);
            }

            if (type == 1) {
                goodsCount.setTotalAmount(goodsCount.getTotalAmount().add(commissionGoodsMq.getSellPrice().multiply(new BigDecimal(commissionGoodsMq.getNumber()))));
                goodsCount.setBuyNumber(goodsCount.getBuyNumber() + commissionGoodsMq.getNumber());
                goodsCount.setOrderNumber(goodsCount.getOrderNumber() + 1);
            }
            if (type == 2) {
                goodsCount.setTotalAmount(goodsCount.getTotalAmount().subtract(commissionGoodsMq.getSellPrice().multiply(new BigDecimal(commissionGoodsMq.getNumber()))));
                goodsCount.setRefundNumber(goodsCount.getRefundNumber() + commissionGoodsMq.getNumber());
            }

            goodsCountMapper.updateById(goodsCount);

            // 获取商品分类统计
            if (commissionGoodsMq.getCategoryId() != null) {
                CategoryCount categoryCount = categoryCountMapper.selectOne(Wrappers.lambdaQuery(CategoryCount.class)
                        .eq(CategoryCount::getCategoryId, commissionGoodsMq.getCategoryId())
                        .eq(CategoryCount::getYear, DateUtil.getCurrentYear())
                        .eq(CategoryCount::getQuarter, DateUtil.getCurrentQuarter()));
                if (categoryCount == null) {
                    categoryCount = new CategoryCount();
                    categoryCount.setCategoryId(commissionGoodsMq.getCategoryId());
                    categoryCount.setTotalAmount(new BigDecimal("0"));
                    categoryCount.setBuyNumber(0);
                    categoryCount.setYear(DateUtil.getCurrentYear());
                    categoryCount.setQuarter(DateUtil.getCurrentQuarter());
                    categoryCountMapper.insert(categoryCount);
                }
                if (type == 1) {
                    categoryCount.setTotalAmount(categoryCount.getTotalAmount().add(commissionGoodsMq.getSellPrice().multiply(new BigDecimal(commissionGoodsMq.getNumber()))));
                    categoryCount.setBuyNumber(categoryCount.getBuyNumber() + commissionGoodsMq.getNumber());
                }
                if (type == 2) {
                    categoryCount.setTotalAmount(categoryCount.getTotalAmount().subtract(commissionGoodsMq.getSellPrice().multiply(new BigDecimal(commissionGoodsMq.getNumber()))));
                    categoryCount.setBuyNumber(categoryCount.getBuyNumber() - commissionGoodsMq.getNumber());
                }
                categoryCountMapper.updateById(categoryCount);
            }
        }
    }

}
